#include "keypad_engine.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "croutine.h"
#include "semphr.h"
#include "shell.h"
#include "bsp.h"

#define LOG_TAG "KEYPAD_DEMO"
#include <elog.h>


/* 按键编号 */
typedef enum
{
    KEYPAD_1 = 0,
    KEYPAD_2,
    KEYPAD_3,
    KEYPAD_MAX
}keypad_num_e;


static keypad_t user_key[KEYPAD_MAX];

static TaskHandle_t s_keypad_test = NULL;

/***************************************************************************************************
 * @fn      user_key_read
 *
 * @brief   读取按键状态
 *
 * @param   无
 *
 * @return  读取到的按键引脚状态（按下/释放） 
 */
static uint8_t user_key_read(void *arg)
{
    uint8_t value = 0;
    keypad_t *key = (keypad_t *)arg;

    /* 按键ID */
    switch (key->id)
    {
        case KEYPAD_1:
            value = READ_KEY1();  /* 读取按键1引脚的状态 */
            break;
        
        case KEYPAD_2:
            value = READ_KEY2();  /* 读取按键2引脚的状态 */
            break;

        case KEYPAD_3:
            value = READ_KEY3();  /* 读取按键3引脚的状态 */
            break;

        default:
            break;
    }

    return value;
}

/***************************************************************************************************
 * @fn      user_key_event_callback
 *
 * @brief   按键事件回调函数
 *
 * @param   arg 函数参数
 *
 * @return  无 
 */
static void user_key_event_callback(void *arg)
{
    keypad_t *key = (keypad_t *)arg;

    /* log输出按键id和按键事件（按下、双击、长按）*/
    log_i("id: [%d], event: [%d]", key->id, key->event);
    
    if (key->id == KEYPAD_1)
    {
        if (keypad_event_read(&user_key[KEYPAD_1]) == KEYPAD_EVENT_SHORT_PRESS)  /* 按键1短按 */
        {
            log_i("KEY1 pressed");
        }
        else if (keypad_event_read(&user_key[KEYPAD_1]) == KEYPAD_EVENT_MULTI_CLICK)  /* 按键1多击 */
        {
            log_i("KEY1 multi click = %d", key->multi_clicks);  /* 输出按键1状态和多击次数 */
        }
        else if (keypad_event_read(&user_key[KEYPAD_1]) == KEYPAD_EVENT_LONG_PRESS)
        {
            log_i("KEY1 long press");
        }
        #if KEYPAD_USE_LONG_HOLD
        else if (keypad_event_read(&user_key[KEYPAD_1]) == KEYPAD_EVENT_LONG_HOLD)  
        {
            log_i("KEY1 long hold out");
        }
        #endif  /* end oif #if KEYPAD_USE_LONG_HOLD */
        else if (keypad_event_read(&user_key[KEYPAD_1]) == KEYPAD_EVENT_LONG_UP)  
        {
            log_i("KEY1 long up");
        }
    }
    else if (key->id == KEYPAD_2)
    {
        if (keypad_event_read(&user_key[KEYPAD_2]) == KEYPAD_EVENT_SHORT_PRESS)  /* 按键2短按 */
        {
            log_i("KEY2 pressed");
        }
        else if (keypad_event_read(&user_key[KEYPAD_2]) == KEYPAD_EVENT_MULTI_CLICK)
        {
            log_i("KEY2 multi click = %d", key->multi_clicks);  /* 输出按键2状态和多击次数 */
        }
        else if (keypad_event_read(&user_key[KEYPAD_2]) == KEYPAD_EVENT_LONG_PRESS)
        {
            log_i("KEY2 long press");
        }
        #if KEYPAD_USE_LONG_HOLD
        else if (keypad_event_read(&user_key[KEYPAD_2]) == KEYPAD_EVENT_LONG_HOLD) 
        {
            log_i("KEY2 long hold out");
        }
        #endif  /* end oif #if KEYPAD_USE_LONG_HOLD */
        else if (keypad_event_read(&user_key[KEYPAD_2]) == KEYPAD_EVENT_LONG_UP)  
        {
            log_i("KEY2 long up");
        }
    }
    else if (key->id == KEYPAD_3)
    {
        if (keypad_event_read(&user_key[KEYPAD_3]) == KEYPAD_EVENT_SHORT_PRESS)  /* 按键3短按 */
        {
            log_i("KEY3 pressed");  
        }
        else if (keypad_event_read(&user_key[KEYPAD_3]) == KEYPAD_EVENT_MULTI_CLICK)
        {
            log_i("KEY3 multi click = %d", key->multi_clicks);  /* 输出按键3状态和多击次数 */
        }
        else if (keypad_event_read(&user_key[KEYPAD_3]) == KEYPAD_EVENT_LONG_PRESS) /* 输出按键3长按 */
        {
            log_i("KEY3 long press");  
        }
        #if KEYPAD_USE_LONG_HOLD
        else if (keypad_event_read(&user_key[KEYPAD_3]) == KEYPAD_EVENT_LONG_HOLD)  
        {
            log_i("KEY3 long hold out");
        }
        #endif  /* end oif #if KEYPAD_USE_LONG_HOLD */
        else if (keypad_event_read(&user_key[KEYPAD_3]) == KEYPAD_EVENT_LONG_UP)  
        {
            log_i("KEY3 long up");
        }
    }
}

/***************************************************************************************************
 * @fn      key_scan_task
 *
 * @brief   按键扫描的任务
 *
 * @param   arg 任务参数
 *
 * @return  无 
 */
static void key_scan_task(void *arg)
{
    while (1)
    {
        keypad_scan();
        vTaskDelay(pdMS_TO_TICKS(10));  /* 10ms扫描一次 */
    }
}

/***************************************************************************************************
 * @fn      user_key_init
 *
 * @brief   初始化用户按键
 *
 * @param   arg 任务参数
 *
 * @return  无 
 */
static void user_key_init(void)
{
    uint8_t i;

    for (i = 0; i < KEYPAD_MAX; i++)
    {
        user_key[i].id = i;
        user_key[i].key_pin_read = user_key_read;
        user_key[i].callback = user_key_event_callback;
        user_key[i].debounce_time = 3;
        user_key[i].long_press_time = 100;

        user_key[i].multi_click_down_timeout = 45;  /* 按下之后超出50ms算多击超时 */
        
        #if KEYPAD_USE_LONG_HOLD
        user_key[i].long_hold_out_time = 10;  /* 长按后每100ms输出一个长按保持事件 */
        #endif  /* end oif #if KEYPAD_USE_LONG_HOLD */

        /* 不想要双击，要把多击超时时间设置为1 */
        // user_key[i].multi_click_down_timeout = 1;

        keypad_register(&user_key[i]);
    }
}

/***************************************************************************************************
 * @fn      ts_keypad
 *
 * @brief   测试按键的命令
 *
 * @param   无
 *
 * @return  已经注册的按键个数 
 */
int ts_keypad(int argc, char **argv)
{
    log_i("run keypad demo");

    log_i("argc = %d", argc);

    taskENTER_CRITICAL();  /* 进入临界区 */
    
    /* 初始化用户按键 */
    user_key_init();
    
    /* 如果用户按键扫描任务没有创建，则创建该任务 */
    if (s_keypad_test == NULL)
    {
        xTaskCreate(key_scan_task, "keypad_test", 128, NULL, 12, &s_keypad_test);
    }
    
    taskEXIT_CRITICAL();  /* 退出临界区 */

    return 0; 
}
ZNS_CMD_EXPORT(ts_keypad, Run FreeRTOS key queue demo);


